const fs = require('fs');
const path = require('path');
const { v4: uuidv4 } = require('uuid');

class WidgetManager {
  constructor(dbManager) {
    this.widgets = new Map();
    this.widgetClasses = new Map();
    this.db = dbManager;
    this.loadWidgets();
    this.loadStoredWidgets();
  }

  loadWidgets() {
    const widgetsDir = path.join(__dirname, '../widgets');
    
    if (!fs.existsSync(widgetsDir)) {
      fs.mkdirSync(widgetsDir, { recursive: true });
      return;
    }

    const widgetFolders = fs.readdirSync(widgetsDir, { withFileTypes: true })
      .filter(dirent => dirent.isDirectory())
      .map(dirent => dirent.name);

    for (const widgetName of widgetFolders) {
      try {
        const widgetPath = path.join(widgetsDir, widgetName, 'index.js');
        if (fs.existsSync(widgetPath)) {
          const WidgetClass = require(widgetPath);
          this.widgetClasses.set(widgetName, WidgetClass);
          console.log(`Loaded widget: ${widgetName}`);
        }
      } catch (error) {
        console.error(`Failed to load widget ${widgetName}:`, error.message);
      }
    }
  }

  getAvailableWidgets() {
    return Array.from(this.widgetClasses.keys()).map(name => {
      const WidgetClass = this.widgetClasses.get(name);
      const widgetInfo = {
        name,
        version: WidgetClass.version || '1.0.0',
        description: WidgetClass.description || 'No description',
        configSchema: WidgetClass.configSchema || {}
      };
      
      // Try to get display name and icon from the widget class
      if (WidgetClass.displayName) {
        widgetInfo.displayName = WidgetClass.displayName;
      } else {
        // Convert camelCase to Title Case
        widgetInfo.displayName = name.replace(/([A-Z])/g, ' $1')
          .replace(/^./, str => str.toUpperCase())
          .replace('Widget', '').trim();
      }
      
      // Add default icons for common widget types
      const widgetIcons = {
        'todo': 'fa-tasks',
        'calendar': 'fa-calendar-alt',
        'clock': 'fa-clock',
        'weather': 'fa-cloud-sun',
        'notes': 'fa-sticky-note',
        'calculator': 'fa-calculator'
      };
      
      widgetInfo.icon = WidgetClass.icon || widgetIcons[name.toLowerCase()] || 'fa-cube';
      
      return widgetInfo;
    });
  }

  async instantiateWidget(widgetName, config = {}, userId) {
    const WidgetClass = this.widgetClasses.get(widgetName);
    
    if (!WidgetClass) {
      throw new Error(`Widget '${widgetName}' not found`);
    }

    const widgetId = uuidv4();
    const widget = new WidgetClass(widgetId, config);
    
    // Set userId and dbManager on widget
    widget.userId = userId;
    widget.setDatabaseManager(this.db);
    
    this.widgets.set(widgetId, widget);
    
    // Save to database
    await this.db.saveWidget({
      id: widgetId,
      name: widgetName,
      config: config
    }, userId);
    
    return widget;
  }

  getWidget(widgetId) {
    return this.widgets.get(widgetId);
  }

  removeWidget(widgetId) {
    const widget = this.widgets.get(widgetId);
    if (widget && typeof widget.destroy === 'function') {
      widget.destroy();
    }
    this.widgets.delete(widgetId);
  }

  getAllWidgets() {
    return Array.from(this.widgets.values());
  }

  // Database methods
  async loadStoredWidgets() {
    try {
      const storedWidgets = await this.db.getWidgets();
      for (const widgetData of storedWidgets) {
        const WidgetClass = this.widgetClasses.get(widgetData.name);
        if (WidgetClass) {
          const widget = new WidgetClass(widgetData.id, widgetData.config);
          widget.userId = widgetData.userId;
          widget.setDatabaseManager(this.db);
          this.widgets.set(widgetData.id, widget);
        }
      }
    } catch (error) {
      console.error('Failed to load stored widgets:', error);
    }
  }

  async removeWidget(widgetId) {
    const widget = this.widgets.get(widgetId);
    if (widget && typeof widget.destroy === 'function') {
      widget.destroy();
    }
    
    // Remove from database
    await this.db.deleteWidget(widgetId);
    
    this.widgets.delete(widgetId);
  }
}

module.exports = WidgetManager;